package com.dongdongqiang.common.query.postgres;

import com.dongdongqiang.common.base.BasePage;
import com.dongdongqiang.common.query.*;
import com.dongdongqiang.common.utils.ReflectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.persistence.Table;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 基本分页查询dao 使用的是jdbcTemplate 只做显示用，不可以在业务操作时使用该方法，会导致事务问题
 * Created by zhangzhenbin on 2017/1/3.
 */

public class PostgresGenericQueryDAO implements GenericQueryDAO {
    private static final Logger logger = LoggerFactory.getLogger(PostgresGenericQueryDAO.class);
    @Autowired
    JdbcTemplate jdbcTemplate;

    public <T> BasePage<T> queryPage(String querySql, Class<T> clazz, int page, int pageSize, Object... params) throws QueryException {
        try {
            String countSql = PostgresQuerySqlToCountSqlConvert.getCountSql(querySql);
            long total = jdbcTemplate.queryForObject(countSql, Long.class, params);
            List<T> list = jdbcTemplate.query(querySql, new AnnotationColumnRowMapper<T>(clazz), params);
            return new BasePage<T>(list, page, pageSize, total);
        } catch (DataAccessException e) {
            throw new QueryException("DataAccessException", e);
        }
    }

    public <S extends PageSearchForm, T> BasePage<T> queryPage(S searchForm, Class<T> clazz) {
        try {
            //构建预定义系统
            List<QueryMethodItem> methodItemList = QueryMethodBuilder.build(searchForm, clazz);
            Table table = clazz.getAnnotation(Table.class);
            Field[] allDeclaredFields = ReflectionUtils.getAllDeclaredFields(clazz);

            //查询SQL初始化
            String querySql = "select t.* ";
            String countSql = " select count(1) ";

            //查询条件
            StringBuilder sqlCondition =
                    new StringBuilder(" from " + table.name() + " t where 1= 1 ");
            List<Object> params = new ArrayList<>();
            QueryMethodBuilder.methodItemListBuilder(methodItemList, sqlCondition, params);

            //排序
            String orderBy;
            if (StringUtils.isNotBlank(searchForm.getOrderBy())) {
                orderBy = searchForm.getOrderBy();
            } else {
                orderBy = OrderByBuilder.getOrderByFields(allDeclaredFields);
            }

            //分页
            StringBuilder limitStringBuilder = new StringBuilder();
            if (searchForm.getPage() != null && searchForm.getPageSize() != null) {
                int offset = (searchForm.getPage() - 1) * searchForm.getPageSize();
                limitStringBuilder.append(" limit ").append(searchForm.getPageSize()).append(" offset ").append(offset);
            }

            querySql = querySql + sqlCondition.toString() + orderBy + limitStringBuilder.toString();
            countSql += sqlCondition;
            List<T> list = jdbcTemplate.query(querySql, new AnnotationColumnRowMapper<T>(clazz), params.toArray());
            Long count = jdbcTemplate.queryForObject(countSql, Long.class, params.toArray());
            logger.debug(querySql);

            return new BasePage<>(list, searchForm.getPage(), searchForm.getPageSize(), count);
        } catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
            return null;
        }
    }
}
